package com.cheng.bos.actionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public abstract class ActionUtils<T> extends ActionSupport implements ModelDriven<T> {
	//定义模型驱动实例
	protected T model;
	//实现模型方法
	@Override
	public T getModel() {
		return model;
	}
	//初始化模型
	public ActionUtils() {
		//获取子类继承该类时所设置的泛型参数
		Type genericSuperclass = this.getClass().getGenericSuperclass();
		ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
		//获取泛型类的class对象
		Class<T> modelClass = (Class<T>) parameterizedType.getActualTypeArguments()[0];
		try {
			//对class对象实例化,并赋值给模型
			model = modelClass.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
			System.out.println("模型构造失败");
		}
	}
	
	//提取分页查询
	protected int page;
	protected int rows;
	public void setPage(int page) {
		this.page = page;
	}
	public void setRows(int rows) {
		this.rows = rows;
	}
	//提取数据压入值栈转json
	protected void pushPageDataToValueStack(Page<T> pagedata) {
		//定义map集合将记录总数和记录值存入
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("total", pagedata.getTotalElements());
		result.put("rows", pagedata.getContent());
		//将map压入值栈
		ActionContext.getContext().getValueStack().push(result);
	}
	//抽取条件查询
	protected Specification<T> getSpecification(T model){
		
		//获取成员变量字段
		Field[] fields = model.getClass().getDeclaredFields();
		Specification<T> specification = new Specification<T>() {
			@Override
			public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				try {
					//遍历成员变量字段集合
					for (Field field : fields) {
						//获取成员变量名
						String fieldname = field.getName();
						//获取成员变量对应的get方法名
						String methodname = "get"+fieldname.substring(0, 1).toUpperCase()+fieldname.substring(1);
						//获取成员变量的get方法
						Method method = model.getClass().getMethod(methodname);
						//判断该方法返回值是否是字符串,是否有值
						if ((String.class).equals(method.getReturnType()) && StringUtils.isNotBlank((String) method.invoke(model))) {
							Predicate p1 = cb.like(root.get(fieldname).as(String.class), "%"+method.invoke(model)+"%");
							list.add(p1);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return cb.and(list.toArray(new Predicate[0]));
			}
		};
		
		return specification;
	}
}
